﻿/*
 * Author: Branimir Topic (uxxx4663)
 * For: UC - ODD - Assignment 2B
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using ARMS.BaseClasses;
using System.Data.SqlClient;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
using System.ComponentModel.DataAnnotations;

namespace ARMS.Models
{
    #region Booking Class
    public class Booking
    {
        public Booking() { }
        public Booking(int id, int customerid, string customername, 
            int workerid, string workername, DateTime dateStamp,
            String note, Boolean active, int shopid)
        {
            this.id = id;
            this.datestamp = dateStamp;
            this.customerid = customerid;
            this.customername = customername;
            this.workerid = workerid;
            this.workername = workername;
            this.note = note;
            this.active = active;
            this.shopid = shopid;
        }
        [Required]
        [Display(Name = "Shop ID *")]
        public int shopid { get; set; }
        [Required]
        [Display(Name = "Booking ID *")]
        public int id { get; set; }
        [Required]
        [Display(Name = "Customer ID *")]
        public int customerid { get; set; }
        [Display(Name = "Customer name")]
        public string customername { get; set; }
        [Required]
        [Display(Name = "Service ID *")]
        public int serviceid { get; set; }
        [Display(Name = "Service name")]
        public string servicename { get; set; }
        [Required]
        [Display(Name = "Worker ID *")]
        public int workerid { get; set; }
        [Display(Name = "Worker name")]
        public string workername { get; set; }
        [Display(Name = "Note")]
        public String note { get; set; }
        //[DataType(DataType.DateTime)]
        [Display(Name = "Enter booking date & time *")]
        public DateTime datestamp { get; set; }
        [Display(Name = "Shcheduled")]
        public Boolean active { get; set; }
    }
    #endregion

    #region BookingAdpter Class
    public class BookingAdpter
    {
        private Booking booking;
        public BookingAdpter()
        {
            booking = new Booking();
        }
        public string shopid
        {
            get { return (booking.shopid == 0) ? "" : booking.shopid.ToString(); }
            set
            {
                try
                {
                    //shopid = value;
                    booking.shopid = Convert.ToInt32(value);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid shop number", e);
                }
            }
        }
        public string id
        {
            get { return (booking.id == 0) ? "" : booking.id.ToString(); }
            set
            {
                try
                {
                    //id = value;
                    booking.id = Convert.ToInt32(value);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid booking id", e);
                }
            }
        }
        public string customerid
        {
            get { return (booking.customerid == 0) ? "" : booking.customerid.ToString(); }
            set
            {
                try
                {
                    //this.customerid = value;
                    booking.customerid = Convert.ToInt32(value);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid customer number", e);
                }
            }
        }
        public string customername
        {
            get { return (booking.customername == null) ? "" : booking.customername; }
            set
            {
                booking.customername = value;
            }
        }
        public string serviceid
        {
            get { return (booking.serviceid == 0) ? "" : booking.serviceid.ToString(); }
            set
            {
                try
                {
                    booking.serviceid = Convert.ToInt32(value);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid service id", e);
                }
            }
        }
        public string servicename
        {
            get { return (booking.servicename == null) ? "" : booking.servicename; }
            set
            {
                booking.servicename = value;
            }
        }
        public string workerid
        {
            get { return (booking.workerid == 0) ? "" : booking.workerid.ToString(); }
            set
            {
                try
                {
                    booking.workerid = Convert.ToInt32(value);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid worker number", e);
                }
            }
        }
        public string workername
        {
            get { return (booking.workername == null ) ? "" : booking.workername.ToString(); }
            set { booking.workername = value; }

        }
        public string note
        {
            get { return (booking.note == null) ? "" : booking.note.ToString(); }
            set { booking.note = value; }
        }
        public string datestamp
        {
            get { return (booking.note == null) ? "" : booking.note.ToString(); }
            set
            {
                try
                {
                    booking.datestamp = ARMS.BaseClasses.ARMSConverter.ToDateTime(value, false);
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid datetime", e);
                }
            }
        }
        public string active
        {
            get { return (booking.note == null) ? "" : booking.note.ToString(); }
            set
            {
                try
                {
                    if (value.ToLower() == "true" || value.ToLower() == "false")
                    {
                        booking.active = Convert.ToBoolean(value);
                    }
                    else
                    {
                        booking.active = Convert.ToInt16(value) == 1;
                    }
                }
                catch (Exception e)
                {
                    throw new Exception("Invalid value for active", e);
                }
            }
        }
        public Booking instance { get { return booking; } }
    }
    #endregion 

    #region BookingList Class
    public class BookingList
    {
        private List<Booking> list;
        public BookingList()
        {
            this.list = new List<Booking>();
        }
        public void add(Booking booking)
        {
            this.list.Add(booking);
        }
        public List<Booking> ToList()
        {
            return list;
        }
        /*
        public Booking find(int id)
        {
            Booking booking = new Booking();
            foreach (Booking item in list)
            {
                if (item.id == id)
                {
                    booking = item;
                    break;
                }
            }
            return booking;
        }
         * */
    }
    #endregion

    #region BookingModel Class
    public class BookingModel : ARMS.BaseClasses.BaseModel
    {
        public BookingList GetBookings(int shopid, bool activeOnly = true)
        {
            string select = @"SELECT * FROM bookingview";
            string where = @"";

            if (shopid > 0) where += String.Format(" shopid = {0}", shopid);
            if (activeOnly) where += (where.Length > 0) ? " AND active = 1" : " active = 1";

            string sql = (where.Length > 0) ? select + " WHERE " + where : select;
            sql += " ORDER BY datestamp, id";

            DataTable data = new DataTable();

            data = OpenTable(sql);

            BookingList list = new BookingList();

            foreach (DataRow r in data.Rows)
            {
                BookingAdpter adaptor = new BookingAdpter();
                adaptor.id              = r["id"].ToString();
                adaptor.customerid      = r["customerid"].ToString();
                adaptor.customername    = r["customername"].ToString();
                adaptor.serviceid       = r["serviceid"].ToString();
                adaptor.servicename     = r["servicename"].ToString();
                adaptor.workerid        = r["workerid"].ToString();
                adaptor.workername      = r["workername"].ToString();
                adaptor.shopid          = r["shopid"].ToString();
                adaptor.active          = r["active"].ToString();
                adaptor.note            = r["note"].ToString();
                adaptor.datestamp       = r["datestamp"].ToString();
                list.add(adaptor.instance);
            }

            return list;
        }
        public BookingList GetBookings(Booking allparams, DateTime fromdate, DateTime todate)
        {
            string select = @"SELECT * FROM bookingview";
            string where = @"";

            if (allparams.shopid > 0) where += String.Format(" shopid = {0}", allparams.shopid);
            if (allparams.active) where += (where.Length > 0) ? " AND active = 1" : " active = 1";

            if (fromdate < todate) 
            {
                string from = ARMSConverter.DateTimeToString(fromdate);
                string to = ARMSConverter.DateTimeToString(todate);

                where += (where.Length > 0) ?
                    String.Format(" AND datestamp BETWEEN '{0}' AND '{1}'", from, to ) :
                    String.Format(" datestamp BETWEEN '{0}' AND '{1}'", from, to);
            }

            if (allparams.customerid > 0) where += (where.Length > 0) ?
                String.Format(" AND customerid = {0}", allparams.customerid) :
                String.Format(" customerid = {0}", allparams.customerid);

            if (allparams.customername != null) where += (where.Length > 0) ?
                String.Format(" AND customername LIKE '%{0}%'", allparams.customername) :
                String.Format(" customername LIKE '%{0}%'", allparams.customername);

            if (allparams.serviceid > 0) where += (where.Length > 0) ?
                String.Format(" AND serviceid = {0}", allparams.serviceid) :
                String.Format(" serviceid = {0}", allparams.serviceid);

            string sql = (where.Length > 0) ? select + " WHERE " + where : select;
            sql += " ORDER BY datestamp, id";

            DataTable data = new DataTable();

            data = OpenTable(sql);

            BookingList list = new BookingList();
            foreach (DataRow r in data.Rows)
            {
                BookingAdpter adaptor = new BookingAdpter();
                adaptor.id = r["id"].ToString();
                adaptor.customerid = r["customerid"].ToString();
                adaptor.customername = r["customername"].ToString();
                adaptor.serviceid = r["serviceid"].ToString();
                adaptor.servicename = r["servicename"].ToString();
                adaptor.workerid = r["workerid"].ToString();
                adaptor.workername = r["workername"].ToString();
                adaptor.shopid = r["shopid"].ToString();
                adaptor.active = r["active"].ToString();
                adaptor.note = r["note"].ToString();
                adaptor.datestamp = r["datestamp"].ToString();
                list.add(adaptor.instance);
            }

            return list;
        }
        public Booking FindBooking(int bookingID)
        {
            string select = @"SELECT * FROM bookingview";
            string where = "";

            if (bookingID != Helper.DummyValue) where += String.Format(@" id={0}", bookingID);

            string sql = (where.Length > 0) ? select + " WHERE " + where : select;

            DataTable data = new DataTable();
            try
            {
                data = OpenTable(sql);
            }
            catch (Exception e)
            {
                throw new Exception("Error reading booking record", e);
            }

            BookingAdpter adaptor = new BookingAdpter();

            if (data.Rows.Count > 0)
            {
                DataRow r = data.Rows[0];
                adaptor.id = r["id"].ToString();
                adaptor.active = r["active"].ToString();
                adaptor.customerid = r["customerid"].ToString();
                adaptor.serviceid = r["serviceid"].ToString();
                adaptor.workerid = r["workerid"].ToString();
                adaptor.note = r["note"].ToString();
                adaptor.datestamp = r["datestamp"].ToString();
                adaptor.customername = r["customername"].ToString();
                adaptor.workername = r["workername"].ToString();
                adaptor.shopid = r["shopid"].ToString();
            }

            return adaptor.instance;
        }
        public bool CreateBooking(Booking booking)
        {
            string formatedSQL = String.Format(
                @"INSERT INTO booking (customerid, serviceid, workerid, datestamp, note, active) VALUES({0}, {1}, {2}, '{3}', '{4}', {5})",
                booking.customerid,
                booking.serviceid,
                booking.workerid,
                ARMSConverter.DateTimeToString(booking.datestamp),
                booking.note,
                Convert.ToInt16(booking.active)
            );

            int rowsAffected = 0;
            try
            {
                rowsAffected = Execute(formatedSQL);
            }
            catch (Exception e)
            {
                throw new Exception("Error creating booking record", e);
            }

            return rowsAffected > 0 && BaseModel.errors == 0;
        }
        public bool SaveBooking(Booking booking)
        {
            string formatedSQL = String.Format(
                @"UPDATE booking SET customerid = {0}, serviceid = {1}, workerid = {2}, datestamp = '{3}', note = '{4}', active = {5} WHERE id = {6}",
                booking.customerid,
                booking.serviceid,
                booking.workerid,
                ARMSConverter.DateTimeToString(booking.datestamp),
                booking.note,
                Convert.ToInt16(booking.active),
                booking.id
            );

            int rowsAffected = 0;
            try
            {
                rowsAffected = Execute(formatedSQL);
            }
            catch (Exception e)
            {
                throw new Exception("Error updating booking record", e);
            }

            return rowsAffected > 0 && BaseModel.errors == 0;
        }
        internal bool CancelBooking(int bookingID)
        {
            // cancelation of the booking is described in use UC-BP03
            string formatedSQL = String.Format(@"UPDATE booking SET active = 0 WHERE id = {0}", bookingID);

            int rowsAffected = 0;
            try
            {
                rowsAffected = Execute(formatedSQL);
            }
            catch (Exception e)
            {
                throw new Exception("Error canceling booking record", e);
            }

            return rowsAffected > 0 && BaseModel.errors == 0;
        }
    }
    #endregion

}
